import { useAtomValue } from "jotai";
import { useDeferredValue, useMemo, useState } from "react";
import { Button, Dropdown, Input, Spin, Tooltip } from "antd";
import SearchIcon from "@/assets/icons/search.svg?jsx";
import ThreeDotsIcon from "@/assets/icons/three-dots.svg?jsx";
import type { IProgram } from "@/lib/types";
import useOnUpdated from "@/lib/hooks/useOnUpdated";
import clsm from "@/lib/utils/clsm";
import useLatestRef from "@/lib/hooks/useLatestRef";
import CreateProgramModal from "./EditProgramModal";
import useFetch from "@/lib/hooks/useFetch";
import { copyProgram, deleteProgram } from "@/lib/api/program";
import { tokenAtom } from "@/store/user";
import { useMessage } from "@/providers/AntdMessageProvider";
import getRequestErrorMessage from "@/lib/utils/getRequestErrorMessage";
import { useModal } from "@/providers/AntdModalProvider";

export type ProgramMenuProps = {
  programs: IProgram[];
  editable?: boolean;
  loading?: boolean;
  onSelectProgram?: (program: IProgram) => Promise<boolean>;
  reloadProgramList: () => void;
};

export default function ProgramMenu(props: ProgramMenuProps) {
  const { editable, programs, loading, onSelectProgram, reloadProgramList } =
    props;
  const [keywords, setKeywords] = useState("");
  const deferredKeywords = useDeferredValue(keywords);
  const [current, setCurrent] = useState<number>();
  const [editProgramModal, setEditProgramModal] = useState({
    visible: false,
    type: undefined as "create" | "edit" | undefined,
    id: undefined as number | undefined,
  });
  const onSelectProgramRef = useLatestRef(onSelectProgram);
  const token = useAtomValue(tokenAtom);
  const message = useMessage();
  const modal = useModal();

  const { refetch: handleDelereProgram } = useFetch({
    fetchFn: (id: number) =>
      deleteProgram(id, token).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
      }),
    onError(error) {
      message.error(getRequestErrorMessage(error));
    },
    onSuccess() {
      reloadProgramList?.();
      message.success("删除成功！");
    },
  });

  const { refetch: handleCopyProgram } = useFetch({
    fetchFn: (id: number) =>
      copyProgram(id, token).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
      }),
    onError(error) {
      message.error(getRequestErrorMessage(error));
    },
    onSuccess() {
      message.success("复制成功！");
      reloadProgramList?.();
    },
  });

  async function handleSelectProgram(program: IProgram) {
    const canSelect = await onSelectProgramRef.current?.(program);
    if (canSelect !== false) {
      setCurrent(program.programId);
    }
  }

  useOnUpdated(() => {
    if (
      !current ||
      !programs.find((program) => program.programId === current)
    ) {
      programs[0] && handleSelectProgram(programs[0]);
    }
  }, [programs]);

  const filteredPrograms = useMemo(() => {
    return programs.filter(
      (program) => program.programName.indexOf(deferredKeywords) !== -1,
    );
  }, [programs, deferredKeywords]);

  return (
    <>
      <div className="flex h-full w-[220px] flex-none flex-col rounded-lg border border-[#090909] bg-[#161616] px-4 py-10">
        <Input
          className="flex-none"
          prefix={<SearchIcon />}
          value={keywords}
          onInput={(e) => setKeywords((e.target as HTMLInputElement).value)}
        />
        <div className="min-h-0 flex-auto pt-4">
          <Spin spinning={loading}>
            <ul className="min-h-20">
              {filteredPrograms.map((program) => (
                <li
                  key={program.programId}
                  className={clsm(
                    "flex cursor-pointer items-center justify-between",
                    current === program.programId && "bg-[#52525b]",
                  )}
                >
                  <Tooltip title={program.programName} placement="right">
                    <div
                      className="min-w-0 flex-auto truncate px-2 py-1"
                      onClick={() => handleSelectProgram(program)}
                    >
                      {program.programName}
                    </div>
                  </Tooltip>
                  {editable && (
                    <Dropdown
                      menu={{
                        items: [
                          {
                            label: "编辑",
                            key: 0,
                            onClick: () => {
                              setEditProgramModal({
                                visible: true,
                                type: "edit",
                                id: program.programId,
                              });
                            },
                          },
                          {
                            label: "复制",
                            key: 1,
                            onClick: () => {
                              handleCopyProgram(program.programId);
                            },
                          },
                          {
                            label: "删除",
                            key: 2,
                            onClick: () => {
                              modal.confirm({
                                content: `确定删除 ${program.programName} 吗？`,
                                okText: "确定",
                                onOk: () =>
                                  handleDelereProgram(program.programId),
                              });
                            },
                          },
                        ],
                      }}
                      trigger={["click"]}
                    >
                      <Button size="small" type="text">
                        <ThreeDotsIcon />
                      </Button>
                    </Dropdown>
                  )}
                </li>
              ))}
            </ul>
          </Spin>
        </div>
        {editable && (
          <div className="flex flex-none justify-between">
            <Button
              onClick={() =>
                setEditProgramModal({
                  visible: true,
                  type: "create",
                  id: undefined,
                })
              }
            >
              添加
            </Button>
            <Button>载入</Button>
          </div>
        )}
      </div>
      <CreateProgramModal
        type={editProgramModal.type}
        visible={editProgramModal.visible}
        programId={editProgramModal.id}
        onClose={() =>
          setEditProgramModal({
            visible: false,
            type: undefined,
            id: undefined,
          })
        }
        onSuccess={reloadProgramList}
      />
    </>
  );
}
